import javax.vecmath.*;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import com.sun.j3d.utils.behaviors.vp.*;
import javax.swing.JFrame;



/**
* Beispiel fuer die Erzeugung eines Objekts (Tetraeder) aus Dreiecken,
* bei denen die Normalenvektoren interpoliert werden.
*
* @author Frank Klawonn
* Letzte Aenderung 05.07.2005
* @see GeomArrayExample
*/
public class NormalsForGeomArrays extends JFrame
{

  //Der Canvas, auf den gezeichnet wird.
  public Canvas3D myCanvas3D;


  public NormalsForGeomArrays()
  {
    //Mechanismus zum Schliessen des Fensters und beenden des Programms
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);


    //Standardeinstellung fuer das Betrachteruniversum
    myCanvas3D = new Canvas3D(SimpleUniverse.getPreferredConfiguration());


    //Aufbau des SimpleUniverse:
    //Zuerst Erzeugen zusammen mit dem Canvas
    SimpleUniverse simpUniv = new SimpleUniverse(myCanvas3D);


    //Standardpositionierung des Betrachters
    simpUniv.getViewingPlatform().setNominalViewingTransform();


    //Die Szene wird in dieser Methode erzeugt.
    createSceneGraph(simpUniv);


    //Hinzufuegen von Licht
    addLight(simpUniv);


    //Hierdurch kann man mit der Maus den Betrachterstandpunkt veraendern
    OrbitBehavior ob = new OrbitBehavior(myCanvas3D);
    ob.setSchedulingBounds(new BoundingSphere(new Point3d(0.0,0.0,0.0),Double.MAX_VALUE));
    simpUniv.getViewingPlatform().setViewPlatformBehavior(ob);


    //Darstellung des Canvas/Fensters:
    setTitle("Statische Szene aus elementaren Objekten");
    setSize(700,700);
    getContentPane().add("Center", myCanvas3D);
    setVisible(true);

  }




  public static void main(String[] args)
  {
     NormalsForGeomArrays nfga = new NormalsForGeomArrays();
  }





  //In dieser Methode werden die Objekte der Szene aufgebaut und dem
  //SimpleUniverse su hinzugefuegt.
  public void createSceneGraph(SimpleUniverse su)
  {


    Appearance yellowApp = new Appearance();
    setToMyDefaultAppearance(yellowApp,new Color3f(0.5f,0.5f,0.0f));


    //Die vier Ecken des Tetraeders
    Point3f[] tetrahedronCoordinates =
      {
        new Point3f(0.5f,0.0f,0.0f),
        new Point3f(-0.5f,0.0f,0.0f),
        new Point3f(0.0f,0.0f,-0.6f),
        new Point3f(0.0f,0.7f,0.0f)
      };


    //Die vier Dreiecke des Tetraeders
    int coordIndices[] =
      {
        0,3,1,
        0,2,3,
        0,1,2,
        1,3,2
      };




    GeometryInfo gi = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
    gi.setCoordinates(tetrahedronCoordinates);
    gi.setCoordinateIndices(coordIndices);
    NormalGenerator ng = new NormalGenerator();

//Hier wird die Interpolation der Normalenvektoren festgelegt.
    ng.setCreaseAngle(Math.PI);

    ng.generateNormals(gi);
    GeometryArray te = gi.getGeometryArray();

    //Erzeugung des Tetraeders als Shape
    Shape3D tetrahedron = new Shape3D(te,yellowApp);

    //Die Transformationsgrupp des Tetraeders
    //Der Tetraeder soll etwas gedreht dargestellt werden:
    Transform3D tfTetrahedron = new Transform3D();
    tfTetrahedron.rotX(0.4*Math.PI);
    TransformGroup tgTetrahedron = new TransformGroup(tfTetrahedron);
    tgTetrahedron.addChild(tetrahedron);


//*** Die Wurzel des Graphen, der die Szene enthaelt. ***
    BranchGroup theScene = new BranchGroup();

    //Hinzufuegen des Tetraeders
    theScene.addChild(tgTetrahedron);

    theScene.compile();

    //Hinzufuegen der Szene
    su.addBranchGraph(theScene);

  }


  /**
  * Erzeugt eine Standardoberflaechenstruktur in einer gewuenschten Farbe
  *
  * @param app      Die Appearance, mit der die Oberflaeche belegt werden soll
  * @param col      Die gewuenschte Farbe
  */
  public static void setToMyDefaultAppearance(Appearance app, Color3f col)
  {
    app.setMaterial(new Material(col,col,col,col,120.0f));
  }



  //Hier wird etwas Licht zu der Szene hinzugefuegt.
  public void addLight(SimpleUniverse su)
  {

    BranchGroup bgLight = new BranchGroup();

    BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.MAX_VALUE);
    Color3f lightColour1 = new Color3f(1.0f,1.0f,1.0f);
    Vector3f lightDir1  = new Vector3f(-1.0f,0.0f,-0.5f);
    DirectionalLight light1 = new DirectionalLight(lightColour1, lightDir1);
    light1.setInfluencingBounds(bounds);


    Vector3f lightDir2  = new Vector3f(1.0f,0.0f,0.5f);
    DirectionalLight light2 = new DirectionalLight(lightColour1, lightDir2);
    light2.setInfluencingBounds(bounds);


    bgLight.addChild(light1);
    bgLight.addChild(light2);

    su.addBranchGraph(bgLight);
  }



}
